package com.xiang.community.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xiang.community.dao.LoginTicketMapper;
import com.xiang.community.dao.UserMapper;
import com.xiang.community.dto.ResultDTO;
import com.xiang.community.dto.UserFocusDTO;
import com.xiang.community.entity.LoginTicket;
import com.xiang.community.entity.User;
import com.xiang.community.enums.*;
import com.xiang.community.utils.MailUtil;
import com.xiang.community.utils.RedisUtil;
import com.xiang.community.utils.RegistryUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

import static com.xiang.community.constant.RedisUtilConstant.*;

@Service
public class UserService {

    @Resource
    private UserMapper userMapper;
    @Resource
    private LoginTicketMapper loginTicketMapper;
    @Resource
    private MailUtil mailUtil;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private ObjectMapper mapper;

    @Value("${community.path.domain}")
    private String domain;

    @Value("${server.servlet.context-path}")
    private String contextPath;

    public User findUserById(int id) {
        return userMapper.selectById(id);
    }

    public void updateHeader(int id, String headerUrl) {
        userMapper.updateHeader(id, headerUrl);
    }

    public ResultDTO register(String username, String password, String email) {
        // 验证账号
        User u = userMapper.selectByName(username);
        if (u != null) {
            return ResultDTO.builder().code(ResponseCodeEnum.CLIENT_ERROR.getCode()).message("注册失败,该账号已存在!").build();
        }

        // 验证邮箱
        u = userMapper.selectByEmail(email);
        if (u != null) {
            return ResultDTO.builder().code(ResponseCodeEnum.CLIENT_ERROR.getCode()).message("注册失败,该邮箱已被注册!").build();
        }

        User user = new User();
        // 注册用户
        user.setUsername(username);
        user.setEmail(email);
        user.setSalt(RegistryUtil.generateUUID().substring(0, 5));
        user.setPassword(RegistryUtil.md5(password + user.getSalt()));
        user.setType(UserTypeEnum.COMMON_USER.getType());
        user.setStatus(UserStatusEnum.INACTIVATED.getStatus());
        user.setActivationCode(RegistryUtil.generateUUID());
        user.setHeaderUrl(String.format("http://images.nowcoder.com/head/%dt.png", new Random().nextInt(1000)));
        user.setCreateTime(new Date());
        userMapper.insertUser(user);

        // 激活邮件
        String url = domain + contextPath + "/activation/" + user.getId() + "/" + user.getActivationCode();
        mailUtil.send("/mail/activation", "账号激活", user.getEmail(), url);

        return ResultDTO.builder().code(ResponseCodeEnum.SUCCESS.getCode())
                .message("注册成功,我们已经向您的邮箱发送了一封激活邮件,请尽快激活!").build();
    }

    public ResultDTO activation(int userId, String code) {
        User user = userMapper.selectById(userId);
        if (user == null) {
            return ResultDTO.builder().code(ResponseCodeEnum.CLIENT_ERROR.getCode()).message("激活失败,账号不存在!").build();
        }
        if (user.getStatus() == UserStatusEnum.ACTIVATED.getStatus()) {
            return ResultDTO.builder().code(ResponseCodeEnum.CLIENT_ERROR.getCode()).message("无效操作,该账号已激活!").build();
        }
        if (user.getActivationCode().equals(code)) {
            userMapper.updateStatus(userId, UserStatusEnum.ACTIVATED.getStatus());
            return ResultDTO.builder().code(ResponseCodeEnum.SUCCESS.getCode()).message("激活成功,您的账号已经可以正常使用了!").build();
        }
        return ResultDTO.builder().code(ResponseCodeEnum.CLIENT_ERROR.getCode()).message("激活失败,激活码错误!").build();
    }

    public ResultDTO login(String username, String password, String kaptcha, String kaptchaTarget) throws JsonProcessingException {
        if (!kaptchaTarget.equals(kaptcha.toUpperCase())) {
            return ResultDTO.builder().code(ResponseCodeEnum.CLIENT_ERROR.getCode()).message("登录失败,验证码错误!").build();
        }

        User currentUser = userMapper.selectByName(username);
        password = RegistryUtil.md5(password + currentUser.getSalt());
        if (currentUser == null || !password.equals(currentUser.getPassword())) {
            return ResultDTO.builder().code(ResponseCodeEnum.CLIENT_ERROR.getCode()).message("登录失败,账号或密码错误!").build();
        }

        if (currentUser.getStatus() == UserStatusEnum.INACTIVATED.getStatus()) {
            return ResultDTO.builder().code(ResponseCodeEnum.CLIENT_ERROR.getCode()).message("登录失败,账号未激活!").build();
        }

        // 生成token
        LoginTicket token = new LoginTicket();
        token.setUserId(currentUser.getId());
        token.setTicket(RegistryUtil.generateUUID());
        token.setStatus(0);
        // 24小时
        token.setExpired(new Date(System.currentTimeMillis() + TokenValidTimeEnum.ONE_DAY.getSeconds() * 1000));
        loginTicketMapper.insertLoginTicket(token);

        User user = userMapper.selectByName(username);
        saveUserInfoToRedis(user);
        redisUtil.saveIntoString(PREFIX_USER_ID, token.getTicket(), user.getId());

        Map<String, Object> map = new HashMap<>(1);
        map.put("token", token);
        return ResultDTO.builder().code(ResponseCodeEnum.SUCCESS.getCode()).data(map).build();
    }

    public LoginTicket findLoginTicket(String token) {
        return loginTicketMapper.selectByTicket(token);
    }

    public ResultDTO logout(String token) {
        loginTicketMapper.updateStatus(token, LoginStatusEnum.INVALID.getStatus());
        redisUtil.removeFromRedis(PREFIX_USER_ID, token);
        return ResultDTO.builder().code(ResponseCodeEnum.SUCCESS.getCode()).build();
    }

    public UserFocusDTO selectFocus(Integer userOneId, Integer userTwoId) {
        return userMapper.selectFocus(userOneId, userTwoId);
    }

    public void insertFocus(UserFocusDTO userFocusDTO) {
        userMapper.insertFocus(userFocusDTO);
    }

    public void updateFocus(Long id, int status) {
        userMapper.updateFocus(id, status);
    }

    public void deleteFocus(Long id) {
        userMapper.deleteFocus(id);
    }

    public void updateField(String field, Object value, Integer userId) {
        userMapper.updateField(field, value, userId);
    }

    public void saveUserInfoToRedis(User user) throws JsonProcessingException {
        // 用户信息
        redisUtil.saveIntoString(PREFIX_USER, user.getId(), mapper.writeValueAsString(user));

        // 关注与被关注信息
        List<Integer> followeeList = userMapper.selectFolloweeList(user.getId());
        saveListToRedis(PREFIX_USER_FOLLOWEE, user.getId(), followeeList);
        List<Integer> followerList = userMapper.selectFollowerList(user.getId());
        saveListToRedis(PREFIX_USER_FOLLOWER, user.getId(), followerList);
    }

    private void saveListToRedis(String prefix, Object key, List<Integer> list) {
        for (Integer value : list) {
            redisUtil.saveIntoSet(prefix, key, value);
        }
    }
}
